from typing import List
from app.models.file_model import StorageProviderModel
from app.schemas.admin.admin_storage_provider_schemas import (
    AdminStorageProviderDetail,
    AdminStorageProviderListFilter,
    AdminStorageProviderResponse,
    AdminStorageProviderCreate,
    AdminStorageProviderUpdate,
)
from app.core.exceptions import APIException
from app.core.storage.factory import StorageFactory
from app.core.i18n import t
from tortoise.transactions import atomic
from logging import getLogger

from app.schemas.response import Response
from app.schemas.common import OrderSchema, PaginationParams, PaginationResult
from app.services.base import filter_query

logger = getLogger(__name__)


class StorageProviderService:
    """
    存储供应商服务
    用于管理存储供应商的创建、更新、删除等操作

    支持功能:
    1. 供应商的CRUD操作
    2. 默认供应商管理
    3. 存储配置验证
    """

    @classmethod
    async def get_provider_list(
        cls, filters: AdminStorageProviderListFilter, order: OrderSchema, pagination: PaginationParams
    ) -> PaginationResult[AdminStorageProviderResponse]:
        """
        获取供应商列表

        Returns:
            PaginationResult[AdminStorageProviderResponse]: 供应商列表
        """
        special_filter_conditions = {
            "name": "name__icontains",
        }
        query = StorageProviderModel.all()
        query = await filter_query(query, filters, special_filter_conditions)
        if order.order_by:
            order_by = order.get_tortoise_orders()
            query = query.order_by(*order_by)
        total = await query.count()
        items = await query.offset(pagination.get_skip()).limit(pagination.page_size).all()
        return PaginationResult(total=total, items=items)

    @classmethod
    @atomic()
    async def create_provider(cls, request: AdminStorageProviderCreate) -> AdminStorageProviderResponse:
        """
        创建供应商

        Args:
            request: 创建供应商请求

        Returns:
            AdminStorageProviderResponse: 创建的供应商信息

        Raises:
            APIException: 配置验证失败时抛出异常
        """
        # 验证配置
        try:
            storage = StorageFactory.create_storage(request.type, **request.config)
            if not await storage.test_connection():
                raise APIException(message=t("error.storage_provider.config_invalid"))
        except Exception as e:
            logger.error(f"存储配置验证失败: {str(e)}", exc_info=True)
            raise APIException(message=t("error.storage_provider.config_invalid"))

        # 处理默认供应商
        if request.is_default:
            await StorageProviderModel.filter(is_default=True).update(is_default=False)

        # 创建供应商
        provider = await StorageProviderModel.create(
            name=request.name, type=request.type, config=request.config, is_default=request.is_default
        )

        return AdminStorageProviderResponse.model_validate(provider)

    @classmethod
    @atomic()
    async def update_provider(cls, request: AdminStorageProviderUpdate) -> AdminStorageProviderResponse:
        """
        更新供应商

        Args:
            request: 更新供应商请求

        Returns:
            AdminStorageProviderResponse: 更新后的供应商信息

        Raises:
            APIException: 供应商不存在或配置验证失败时抛出异常
        """
        # 获取供应商
        provider = await StorageProviderModel.get_or_none(id=request.id)
        if not provider:
            raise APIException(message=t("error.storage_provider.not_found"))

        # 如果更新了配置，需要验证
        if request.config:
            try:
                storage = StorageFactory.create_storage(provider.type, **request.config)
                if not await storage.test_connection():
                    raise APIException(message=t("error.storage_provider.config_invalid"))
            except Exception as e:
                logger.error(f"存储配置验证失败: {str(e)}", exc_info=True)
                raise APIException(message=t("error.storage_provider.config_invalid"))

        # 处理默认供应商
        if request.is_default:
            await StorageProviderModel.filter(is_default=True).update(is_default=False)

        # 更新供应商
        update_data = request.dict(exclude_unset=True, exclude={"id"})
        await provider.update_from_dict(update_data)
        await provider.save()

        return AdminStorageProviderResponse.model_validate(provider)

    @classmethod
    @atomic()
    async def delete_provider(cls, provider_id: int) -> None:
        """
        删除供应商

        Args:
            provider_id: 供应商ID

        Raises:
            APIException: 供应商不存在或存在关联文件时抛出异常
        """
        # 获取供应商
        provider = await StorageProviderModel.get_or_none(id=provider_id)
        if not provider:
            raise APIException(message=t("error.storage_provider.not_found"))

        # 检查是否有关联的文件
        if await provider.files.count() > 0:
            raise APIException(message=t("error.storage_provider.has_files"))

        # 如果是默认供应商，需要重新指定默认供应商
        if provider.is_default:
            other_provider = await StorageProviderModel.filter(id__not=provider_id).first()
            if other_provider:
                other_provider.is_default = True
                await other_provider.save()

        # 删除供应商
        await provider.delete()

    @classmethod
    @atomic()
    async def set_default_provider(cls, provider_id: int) -> None:
        """
        设置默认供应商

        Args:
            provider_id: 供应商ID

        Raises:
            APIException: 供应商不存在时抛出异常
        """
        # 获取供应商
        provider = await StorageProviderModel.get_or_none(id=provider_id)
        if not provider:
            raise APIException(message=t("error.storage_provider.not_found"))

        # 更新默认供应商
        await StorageProviderModel.filter(is_default=True).update(is_default=False)
        provider.is_default = True
        await provider.save()

    @classmethod
    async def get_provider_detail(cls, provider_id: int) -> AdminStorageProviderDetail:
        """
        获取供应商详情

        Args:
            provider_id: 供应商ID

        Returns:
            AdminStorageProviderDetail: 供应商详情

        Raises:
            APIException: 供应商不存在时抛出异常
        """
        provider = await StorageProviderModel.get_or_none(id=provider_id)
        if not provider:
            raise APIException(message=t("error.storage_provider.not_found"))
        return AdminStorageProviderDetail.model_validate(provider)
